package com.frank.oj.manager;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.frank.model.entity.common.Announcement;
import com.frank.model.entity.contest.*;
import com.frank.model.entity.judge.Judge;
import com.frank.model.entity.problem.*;
import com.frank.model.entity.training.Training;
import com.frank.model.entity.user.UserInfo;
import com.frank.oj.common.exception.StatusFailException;
import com.frank.oj.common.exception.StatusForbiddenException;
import com.frank.oj.common.exception.StatusNotFoundException;
import com.frank.oj.constant.Constants;
import com.frank.oj.model.bo.Pair_;
import com.frank.oj.model.dto.ContestPrintDTO;
import com.frank.oj.model.dto.ContestRankDTO;
import com.frank.oj.model.dto.RegisterContestDTO;
import com.frank.oj.model.dto.UserReadContestAnnouncementDTO;
import com.frank.oj.model.vo.*;
import com.frank.oj.service.entity.common.AnnouncementEntityService;
import com.frank.oj.service.entity.common.TagEntityService;
import com.frank.oj.service.entity.contest.*;
import com.frank.oj.service.entity.group.GroupMemberEntityService;
import com.frank.oj.service.entity.judge.JudgeEntityService;
import com.frank.oj.service.entity.problem.*;
import com.frank.oj.service.entity.user.UserInfoEntityService;
import com.frank.oj.shiro.AccountProfile;
import com.frank.oj.utils.RedisUtils;
import com.frank.oj.validator.ContestValidator;
import com.frank.oj.validator.GroupValidator;
import com.frank.oj.validator.TrainingValidator;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author frank
 * @Date 2024/4/5
 */
@Component
public class ContestManager {
    @Resource
    private ContestEntityService contestEntityService;

    @Resource
    private ContestRecordEntityService contestRecordEntityService;

    @Resource
    private ContestProblemEntityService contestProblemEntityService;

    @Resource
    private ContestAnnouncementEntityService contestAnnouncementEntityService;

    @Resource
    private AnnouncementEntityService announcementEntityService;

    @Resource
    private ContestRegisterEntityService contestRegisterEntityService;

    @Resource
    private ProblemEntityService problemEntityService;

    @Resource
    private ProblemTagEntityService problemTagEntityService;

    @Autowired
    private TagEntityService tagEntityService;

    @Resource
    private LanguageEntityService languageEntityService;

    @Resource
    private ProblemLanguageEntityService problemLanguageEntityService;

    @Resource
    private JudgeEntityService judgeEntityService;

    @Resource
    private CodeTemplateEntityService codeTemplateEntityService;

    @Resource
    private ContestPrintEntityService contestPrintEntityService;

    @Resource
    private UserInfoEntityService userInfoEntityService;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private ContestValidator contestValidator;

    @Resource
    private ContestRankManager contestRankManager;

    @Resource
    private GroupMemberEntityService groupMemberEntityService;

    @Resource
    private GroupValidator groupValidator;

    public ContestVO getContestInfo(Long cid) throws StatusFailException, StatusForbiddenException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        ContestVO contestVO = contestEntityService.getContestInfoById(cid);
        if (contestVO == null) {
            throw new StatusFailException("比赛信息不存在");
        }
        Contest contest = contestEntityService.getById(cid);
        if (contest.getIsGroup()) {
            if (!groupValidator.isGroupMember(userRole.getUid(), contest.getGid()) && !isRoot) {
                throw new StatusForbiddenException("对不起，您无权限操作！");
            }
        }
        contestVO.setNow(new Date());
        return contestVO;
    }

    public IPage<AnnouncementVO> getContestAnnouncement(Long cid, Integer limit, Integer currentPage) throws StatusForbiddenException, StatusFailException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Contest contest = contestEntityService.getById(cid);

        // 权限校验：包括私有比赛密码等
        contestValidator.validateContestAuth(contest, userRole, isRoot);

        if (currentPage == null || currentPage < 1) currentPage = 1;
        if (limit == null || limit < 1) limit = 10;

        return announcementEntityService.getContestAnnouncement(cid, true, limit, currentPage);

    }

    public List<Announcement> getContestUserNotReadAnnouncement(UserReadContestAnnouncementDTO userReadContestAnnouncementDto) {
        Long cid = userReadContestAnnouncementDto.getCid();
        List<Long> readAnnouncementList = userReadContestAnnouncementDto.getReadAnnouncementList();

        LambdaQueryWrapper<ContestAnnouncement> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ContestAnnouncement::getCid, cid);
        if (readAnnouncementList != null && !readAnnouncementList.isEmpty()) {
            queryWrapper.notIn(ContestAnnouncement::getAid, readAnnouncementList); //已读列表
        }

        List<ContestAnnouncement> announcementList = contestAnnouncementEntityService.list(queryWrapper);
        List<Long> aidList = announcementList.stream().map(ContestAnnouncement::getAid).collect(Collectors.toList());

        if (!aidList.isEmpty()) {
            LambdaQueryWrapper<Announcement> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Announcement::getId, aidList).orderByDesc(Announcement::getGmtCreate);

            return announcementEntityService.list(wrapper);
        } else {
            return new ArrayList<>();
        }
    }

    public List<ContestProblemVO> getContestProblem(Long cid, Boolean isContainsContestEndJudge) throws StatusForbiddenException, StatusFailException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Contest contest = contestEntityService.getById(cid);

        List<String> groupRootUidList = null;

        if (contest.getIsGroup() && contest.getGid() != null) {
            groupRootUidList = groupMemberEntityService.getGroupRootUidList(contest.getGid());
        }

        isContainsContestEndJudge = Objects.equals(contest.getAllowEndSubmit(), true) && isContainsContestEndJudge;

        if (userRole == null) {
            if (Objects.equals(contest.getOpenRank(), true) && contest.getStatus().intValue() != Constants.Contest.STATUS_SCHEDULED.getCode()) {
                return contestProblemEntityService.getContestProblemList(
                        cid,
                        contest.getStartTime(),
                        contest.getEndTime(),
                        Objects.equals(contest.getSealRank(), true) ? contest.getSealRankTime() : null,
                        false,
                        contest.getAuthor(),
                        groupRootUidList,
                        isContainsContestEndJudge);
            } else {
                throw new StatusForbiddenException("请先登录！");
            }
        }

        // 未开放赛外榜单，需要鉴权
        if (!Objects.equals(contest.getOpenRank(), true)) {
            contestValidator.validateContestAuth(contest, userRole, isRoot);
        }

        List<ContestProblemVO> contestProblemList;
        boolean isAdmin = isRoot || contest.getAuthor().equals(userRole.getUsername()) || (contest.getIsGroup() && groupValidator.isGroupRoot(userRole.getUid(), contest.getGid()));

        //开启了封榜
        if (contestValidator.isSealRank(userRole.getUid(), contest, true, isRoot)) {
            contestProblemList = contestProblemEntityService.getContestProblemList(cid,
                    contest.getStartTime(), contest.getEndTime(), contest.getSealRankTime(), isAdmin, contest.getAuthor(), groupRootUidList, isContainsContestEndJudge);
        } else {
            contestProblemList = contestProblemEntityService.getContestProblemList(cid,
                    contest.getStartTime(), contest.getEndTime(), null, isAdmin, contest.getAuthor(), groupRootUidList, isContainsContestEndJudge);
        }
        return contestProblemList;
    }

    public ProblemInfoVO getContestProblemDetails(Long cid, String displayId, Boolean isContainsContestEndJudge) throws StatusForbiddenException, StatusFailException, StatusNotFoundException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Contest contest = contestEntityService.getById(cid);
        contestValidator.validateContestAuth(contest, userRole, isRoot);

        LambdaQueryWrapper<ContestProblem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ContestProblem::getCid, cid).eq(ContestProblem::getDisplayId, displayId);
        ContestProblem contestProblem = contestProblemEntityService.getOne(queryWrapper);

        if (contestProblem == null) {
            throw new StatusNotFoundException("题目不存在");
        }

        Problem problem = problemEntityService.getById(contestProblem.getPid());
        if (problem.getAuth() == 2) {
            throw new StatusForbiddenException("该题目当前无法查看");
        }

        problem.setTitle(contestProblem.getDisplayTitle());

        List<Tag> tags = new LinkedList<>();

        if (contest.getStatus().intValue() != Constants.Contest.STATUS_ENDED.getCode()) {
            problem.setSource(null);
            problem.setAuthor(null);
            problem.setDifficulty(null);

            LambdaQueryWrapper<ProblemTag> tagLambdaQueryWrapper = new LambdaQueryWrapper<>();
            tagLambdaQueryWrapper.eq(ProblemTag::getPid, contestProblem.getPid());

            List<Long> tidList = new LinkedList<>();
            problemTagEntityService.list(tagLambdaQueryWrapper).forEach(problemTag -> {
                tidList.add(problemTag.getTid());
            });

            if (!tidList.isEmpty()) {
                tags = (List<Tag>) tagEntityService.listByIds(tidList);
            }
        }

        HashMap<Long, String> tmpMap = new HashMap<>();
        List<String> languagesStr = new LinkedList<>();

        LambdaQueryWrapper<ProblemLanguage> languageLambdaQueryWrapper = new LambdaQueryWrapper<>();
        languageLambdaQueryWrapper.eq(ProblemLanguage::getPid, contestProblem.getPid()).select(ProblemLanguage::getLid);
        List<Long> lidList = problemLanguageEntityService.list(languageLambdaQueryWrapper).stream().map(ProblemLanguage::getLid).collect(Collectors.toList());

        Collection<Language> languages = languageEntityService.listByIds(lidList);
        languages = languages.stream().sorted(Comparator.comparing(Language::getSeq, Comparator.reverseOrder()).thenComparing(Language::getId))
                .collect(Collectors.toList());

        languages.forEach(language -> {
            languagesStr.add(language.getName());
            tmpMap.put(language.getId(), language.getName());
        });

        Date sealRankTime = null;
        //封榜时间除超级管理员和比赛管理员外 其它人不可看到最新数据
        if (contestValidator.isSealRank(userRole.getUid(), contest, true, isRoot)) {
            sealRankTime = contest.getSealRankTime();
        } else {
            isContainsContestEndJudge = Objects.equals(contest.getAllowEndSubmit(), true) && Objects.equals(isContainsContestEndJudge, true);

            // 如果比赛结束任不允许提交，则封榜时间设置为比赛结束时间
            if (!isContainsContestEndJudge) {
                sealRankTime = contest.getEndTime();
            }
        }
        List<String> superAdminUidList = userInfoEntityService.getSuperAdminUidList();
        superAdminUidList.add(contest.getUid());

        ProblemCountVO problemCount = judgeEntityService.getContestProblemCount(contestProblem.getPid(), contestProblem.getId(), contestProblem.getCid()
                , contest.getStartTime(), sealRankTime, superAdminUidList);

        LambdaQueryWrapper<CodeTemplate> templateLambdaQueryWrapper = new LambdaQueryWrapper<>();
        templateLambdaQueryWrapper.eq(CodeTemplate::getPid, problem.getId()).eq(CodeTemplate::getStatus, true);
        List<CodeTemplate> codeTemplates = codeTemplateEntityService.list(templateLambdaQueryWrapper);
        HashMap<String, String> langNameAndCode = new HashMap<>();

        if (!codeTemplates.isEmpty()) {
            for (CodeTemplate codeTemplate : codeTemplates) {
                langNameAndCode.put(tmpMap.get(codeTemplate.getLid()), codeTemplate.getCode());
            }
        }

        return new ProblemInfoVO(problem, tags, languagesStr, problemCount, langNameAndCode);
    }

    public IPage<JudgeVO> getContestSubmissionList(Integer limit,
                                                   Integer currentPage,
                                                   Boolean onlyMine,
                                                   String displayId,
                                                   Integer searchStatus,
                                                   String searchUsername,
                                                   Long searchCid,
                                                   Boolean beforeContestSubmit,
                                                   Boolean completeProblemID,
                                                   Boolean isContainsContestEndJudge) throws StatusForbiddenException, StatusFailException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Contest contest = contestEntityService.getById(searchCid);
        contestValidator.validateContestAuth(contest, userRole, isRoot);

        if (currentPage == null || currentPage < 1) currentPage = 1;
        if (limit == null || limit < 1) limit = 30;

        String uid = null;
        if (onlyMine) {
            uid = userRole.getUid();
        }

        String rule;
        if (contest.getType().intValue() == Constants.Contest.TYPE_ACM.getCode()) {
            rule = Constants.Contest.TYPE_ACM.getName();
        } else {
            rule = Constants.Contest.TYPE_OI.getName();
        }

        Date sealRankTime = null;
        if (contestValidator.isSealRank(userRole.getUid(), contest, true, isRoot)) {
            sealRankTime = contest.getSealRankTime();
        } else {
            isContainsContestEndJudge = Objects.equals(contest.getAllowEndSubmit(), true)
                    && Objects.equals(isContainsContestEndJudge, true);
            if (!isContainsContestEndJudge) {
                sealRankTime = contest.getSealRankTime();
            }
        }

        IPage<JudgeVO> contestJudgeList = judgeEntityService.getContestJudgeList(limit,
                currentPage,
                displayId,
                searchCid,
                searchStatus,
                searchUsername,
                uid,
                beforeContestSubmit,
                rule,
                contest.getStartTime(),
                sealRankTime,
                userRole.getUid(),
                completeProblemID);

        if (contestJudgeList.getTotal() == 0) {
            return contestJudgeList;
        } else {
            if (contest.getStatus().intValue() == Constants.Contest.STATUS_RUNNING.getCode() && !isRoot && !userRole.getUid().equals(contest.getUid())) {
                contestJudgeList.getRecords().forEach(judgeVO -> {
                    if (!judgeVO.getUid().equals(userRole.getUid())) {
                        judgeVO.setTime(null);
                        judgeVO.setMemory(null);
                        judgeVO.setLength(null);
                    }
                });
            }
            return contestJudgeList;
        }
    }

    public IPage getContestRank(ContestRankDTO contestRankDTO) throws StatusFailException, StatusForbiddenException {
        Long cid = contestRankDTO.getCid();
        List<String> concernedList = contestRankDTO.getConcernedList();
        Integer currentPage = contestRankDTO.getCurrentPage();
        Integer limit = contestRankDTO.getLimit();
        Boolean removeStar = contestRankDTO.getRemoveStar();
        Boolean forceRefresh = contestRankDTO.getForceRefresh();

        if (currentPage == null || currentPage < 1) currentPage = 1;
        if (limit == null || limit < 1) limit = 50;

        if (cid == null) {
            throw new StatusFailException("需提供比赛编号");
        }
        if (removeStar == null) {
            removeStar = false;
        }
        if (forceRefresh == null) {
            forceRefresh = false;
        }

        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Contest contest = contestEntityService.getById(contestRankDTO.getCid());
        contestValidator.validateContestAuth(contest, userRole, isRoot);

        boolean isOpenSealRank = contestValidator.isSealRank(userRole.getUid(), contest, forceRefresh, isRoot);
        boolean isContainsAfterContestJudge = Objects.equals(contest.getAllowEndSubmit(), true)
                && Objects.equals(contestRankDTO.getContainsEnd(), true);

        IPage resultList;
        if (contest.getType().intValue() == Constants.Contest.TYPE_ACM.getCode()) {
            resultList = contestRankManager.getContestACMRankPage(isOpenSealRank,
                    removeStar,
                    userRole.getUid(),
                    concernedList,
                    contestRankDTO.getExternalCidList(),
                    contest,
                    currentPage,
                    limit,
                    contestRankDTO.getKeyword(),
                    isContainsAfterContestJudge);
        } else {
            resultList = contestRankManager.getContestOIRankPage(isOpenSealRank,
                    removeStar,
                    userRole.getUid(),
                    concernedList,
                    contestRankDTO.getExternalCidList(),
                    contest,
                    currentPage,
                    limit,
                    contestRankDTO.getKeyword(),
                    isContainsAfterContestJudge);
        }
        return resultList;
    }

    public void submitPrintText(ContestPrintDTO contestPrintDto) throws StatusForbiddenException, StatusFailException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Contest contest = contestEntityService.getById(contestPrintDto.getCid());

        contestValidator.validateContestAuth(contest, userRole, isRoot);

        String lockKey = Constants.Account.CONTEST_ADD_PRINT_LOCK.getCode() + userRole.getUid();
        if (redisUtils.hasKey(lockKey)) {
            long expire = redisUtils.getExpire(lockKey);
            throw new StatusForbiddenException("提交打印功能限制，请在" + expire + "秒后再进行提交！");
        } else {
            redisUtils.set(lockKey, 1, 30);
        }

        boolean saved = contestPrintEntityService.saveOrUpdate(new ContestPrint()
                .setCid(contestPrintDto.getCid())
                .setContent(contestPrintDto.getContent())
                .setUsername(userRole.getUsername())
                .setRealname(userRole.getRealname()));

        if (!saved) {
            throw new StatusFailException("提交打印失败");
        }
    }

    public AccessVO getContestAccess(Long cid) throws StatusFailException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();

        LambdaQueryWrapper<ContestRegister> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ContestRegister::getCid, cid).eq(ContestRegister::getUid, userRole.getUid());
        ContestRegister contestRegister = contestRegisterEntityService.getOne(queryWrapper, false);

        boolean access = false;
        if (contestRegister != null) {
            access = true;
            Contest contest = contestEntityService.getById(cid);
            if (contest == null || !contest.getVisible()) {
                throw new StatusFailException("比赛不存在");
            }
            if (contest.getOpenAccountLimit() && !contestValidator.validateAccountRule(contest.getAccountLimitRule(), userRole.getUsername())) {
                access = false;
                contestRegisterEntityService.removeById(contestRegister.getId());
            }
        }

        AccessVO accessVO = new AccessVO();
        accessVO.setAccess(access);
        return accessVO;
    }

    public void toRegisterContest(RegisterContestDTO registerContestDto) throws StatusFailException, StatusForbiddenException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Long cid = registerContestDto.getCid();
        String password = registerContestDto.getPassword();
        if (cid == null || StringUtils.isEmpty(password)) {
            throw new StatusFailException("参数错误！");
        }

        Contest contest = contestEntityService.getById(cid);
        if (contest == null || !contest.getVisible()) {
            throw new StatusFailException("比赛不存在！");
        }
        if (contest.getIsGroup()) {
            if (!groupValidator.isGroupMember(userRole.getUid(), contest.getGid()) && !isRoot) {
                throw new StatusForbiddenException("无权限");
            }
        }

        if (!contest.getPwd().equals(password)) {
            throw new StatusFailException("密码错误！");
        }

        if (contest.getOpenAccountLimit()
                && !contestValidator.validateAccountRule(contest.getAccountLimitRule(), userRole.getUsername())) {
            throw new StatusFailException("对不起！本次比赛只允许特定账号规则的用户参赛！");
        }

        LambdaQueryWrapper<ContestRegister> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ContestRegister::getCid, cid).eq(ContestRegister::getUid, userRole.getUid());
        if (contestRegisterEntityService.getOne(queryWrapper, false) != null) {
            throw new StatusFailException("您已报名，请勿重复报名！");
        }

        boolean saved = contestRegisterEntityService.saveOrUpdate(new ContestRegister().setCid(cid).setUid(userRole.getUid()));
        if (!saved) {
            throw new StatusFailException("报名失败！");
        }
    }

    public List<ProblemFullScreenListVO> getContestFullScreenProblemList(Long cid) throws StatusFailException, StatusForbiddenException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Contest contest = contestEntityService.getById(cid);

        // 需要对该比赛做判断，是否处于开始或结束状态才可以获取题目列表，同时若是私有赛需要判断是否已注册（比赛管理员包括超级管理员可以直接获取）
        contestValidator.validateContestAuth(contest, userRole, isRoot);

        List<ProblemFullScreenListVO> problemList = contestProblemEntityService.getContestFullScreenProblemList(cid);
        List<Long> pidList = problemList.stream().map(ProblemFullScreenListVO::getPid).collect(Collectors.toList());

        QueryWrapper<Judge> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("distinct pid,status,score,submit_time")
                .in("pid", pidList)
                .eq("uid", userRole.getUid())
                .orderByDesc("submit_time");
        queryWrapper.eq("cid", cid);

        boolean isACMContest = contest.getType().intValue() == Constants.Contest.TYPE_ACM.getCode();

        List<Judge> judges = judgeEntityService.list(queryWrapper);

        boolean isSealRank = false;
        if (!isACMContest && CollectionUtil.isNotEmpty(judges)) {
            isSealRank = contestValidator.isSealRank(userRole.getUid(), contest, false, isRoot);
        }

        HashMap<Long, Pair_<Integer, Integer>> pidMap = new HashMap<>();
        for (Judge judge : judges) {
            if (Objects.equals(judge.getStatus(), Constants.Judge.STATUS_PENDING.getStatus())
                    || Objects.equals(judge.getStatus(), Constants.Judge.STATUS_COMPILING.getStatus())
                    || Objects.equals(judge.getStatus(), Constants.Judge.STATUS_JUDGING.getStatus())) {
                continue;
            }
            if (!isACMContest) {
                if (!pidMap.containsKey(judge.getPid())) {
                    // IO比赛的，如果还未写入，则使用最新一次提交的结果
                    // 判断该提交是否为封榜之后的提交,OI赛制封榜后的提交看不到提交结果，
                    // 只有比赛结束可以看到,比赛管理员与超级管理员的提交除外
                    if (isSealRank) {
                        pidMap.put(judge.getPid(), new Pair_<>(Constants.Judge.STATUS_SUBMITTED_UNKNOWN_RESULT.getStatus(), null));
                    } else {
                        pidMap.put(judge.getPid(), new Pair_<>(judge.getStatus(), judge.getScore()));
                    }
                }
            } else {
                if (judge.getStatus().intValue() == Constants.Judge.STATUS_ACCEPTED.getStatus()) {
                    // 如果该题目已通过，且同时是为不封榜前提交的，则强制写为通过（0）
                    pidMap.put(judge.getPid(), new Pair_<>(judge.getStatus(), judge.getScore()));
                } else if (!pidMap.containsKey(judge.getPid())) {
                    // 还未写入，则使用最新一次提交的结果
                    pidMap.put(judge.getPid(), new Pair_<>(judge.getStatus(), judge.getScore()));
                }
            }
        }
        for (ProblemFullScreenListVO problemVO : problemList) {
            Pair_<Integer, Integer> pair_ = pidMap.get(problemVO.getPid());
            if (pair_ != null) {
                problemVO.setStatus(pair_.getKey());
                problemVO.setScore(pair_.getValue());
            }
        }
        return problemList;
    }

    public List<RegisterVO> getContestMember(Long cid) throws StatusForbiddenException, StatusFailException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Contest contest = contestEntityService.getById(cid);
        contestValidator.validateContestAuth(contest, userRole, isRoot);

        // 仅管理员可见
        if (!isRoot && !contest.getUid().equals(userRole.getUid()) &&
                !(contest.getIsGroup() && groupValidator.isGroupRoot(userRole.getUid(), contest.getGid()))) {
            throw new StatusForbiddenException("无权限");
        }

        ArrayList<RegisterVO> registerList = new ArrayList<>();

        LambdaQueryWrapper<ContestRegister> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ContestRegister::getCid, cid);
        List<ContestRegister> list = contestRegisterEntityService.list(queryWrapper);
        list.forEach(contestRegister -> {
            RegisterVO registerVO = new RegisterVO();
            registerVO.setUid(contestRegister.getUid());
            UserInfo userInfo = userInfoEntityService.getById(contestRegister.getUid());
            registerVO.setUsername(userInfo.getUsername());
            registerVO.setNickname(userInfo.getNickname());
            registerVO.setAvatar(userInfo.getAvatar());
            registerVO.setAuth(contestRegister.getStatus());
            registerVO.setGmtCreate(contestRegister.getGmtCreate());
            registerList.add(registerVO);
        });

        return registerList;
    }

    public void updateContestMemberStatus(Long contestId, String username, Integer auth) throws StatusForbiddenException, StatusFailException {
        AccountProfile userRole = (AccountProfile) SecurityUtils.getSubject().getPrincipal();
        boolean isRoot = SecurityUtils.getSubject().hasRole("root");

        Contest contest = contestEntityService.getById(contestId);
        contestValidator.validateContestAuth(contest, userRole, isRoot);

        // 仅管理员可见
        if (!isRoot && !contest.getUid().equals(userRole.getUid()) &&
                !(contest.getIsGroup() && groupValidator.isGroupRoot(userRole.getUid(), contest.getGid()))) {
            throw new StatusForbiddenException("无权限");
        }

        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<UserInfo> wrapper = queryWrapper.eq(UserInfo::getUsername, username).select(UserInfo::getUuid);
        UserInfo userInfo = userInfoEntityService.getOne(wrapper);

        LambdaUpdateWrapper<ContestRegister> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(ContestRegister::getCid,contestId).eq(ContestRegister::getUid,userInfo.getUuid()).set(ContestRegister::getStatus,auth);
        boolean updated = contestRegisterEntityService.update(updateWrapper);

        if (!updated){
            throw new StatusFailException("更新失败");
        }
    }
}
